﻿#ifndef __AVOID_CONTROL_INTERFACE_BACKGROUND_HEAD_FILE_INCLUDED__
#define __AVOID_CONTROL_INTERFACE_BACKGROUND_HEAD_FILE_INCLUDED__
#include "../control.h"

namespace swui
{
	/* IBackground 接口提供了背景控制
	 * 绘制的顺序是 BackImage、Fill & Border、ForeImage */
	class IBackground : virtual public ctlRoot
	{
	public:
		enum class borderStyle : unsigned {
			solid, dash, dot, dashDot, 
			dashDotDot, empty
		};
		//除了最后两个，其余与 Gdiplus::HatchStyle 相同
		enum class fillStyle : unsigned {
			  horizontal, vertical, 
			  forwardDiagonal,
			  backwardDiagonal,
			  cross, diagonalCross,
			  percent05, percent10,
			  percent20, percent25,
			  percent30, percent40,
			  percent50, percent60,
			  percent70, percent75,
			  percent80, percent90,
			  lightDownwardDiagonal,
			  lightUpwardDiagonal,
			  darkDownwardDiagonal,
			  darkUpwardDiagonal,
			  wideDownwardDiagonal,
			  wideUpwardDiagonal,
			  lightVertical, lightHorizontal,
			  narrowVertical, narrowHorizontal,
			  darkVertical, darkHorizontal,
			  dashedDownwardDiagonal,
			  dashedUpwardDiagonal,
			  dashedHorizontal, dashedVertical,
			  smallConfetti, largeConfetti,
			  zigZag, wave, diagonalBrick,
			  horizontalBrick, weave,
			  plaid, divot, dottedGrid,
			  dottedDiamond,
			  shingle, trellis,
			  sphere, smallGrid,
			  smallCheckerBoard,
			  largeCheckerBoard,
			  outlinedDiamond,
			  solidDiamond, 
			  solid = 1000, empty
		};
	public:
		//这个值可以用在 setBackImage 和 setForeImage 上，表示无图像
		static const unsigned imageNull = 0xffffffff;
		typedef ctlImageRepeat imageRepeat;
	public:
		IBackground();
		virtual ~IBackground() {}
	public:
		void enableBackground(bool enable);
		bool isBackgroundEnabled();
	public:
		//设置背景填充色（rgba）
		void setBkFillColor(ctlColor);
		//设置背景阴影色（rgba）
		void setBkHatchColor(ctlColor);
		//设置背景边框色（rgba）
		void setBkBorderColor(ctlColor);
		//获取背景填充色
		ctlColor getBkFillColor();
		//获取背景阴影色
		ctlColor getBkHatchColor();
		//获取背景边框色
		ctlColor getBkBorderColor();
		//设置边框样式
		void setBkBorderStyle(borderStyle);
		//获取边框样式
		borderStyle getBkBorderStyle();
		//设置填充样式
		void setBkFillStyle(fillStyle);
		//获取填充样式
		fillStyle getBkFillStyle();
		/* 设置边框填充部分
		  * 例如，0B1111，表示全部绘制
		  * 0B1100，表示绘制上边框和右边框
		  * 二进制位的顺序是：上右下左（顺时针）*/
		void setBkBorderDirectory(unsigned char);
		unsigned char getBkBorderDirectory();
		//设置背景渐变色（与除了 solid 的填充样式不兼容）
		void setBkFillGradientEnd(ctlColor, bool enable = true);
		//获取背景渐变色
		ctlColor getBkFillGradientEnd();
		bool isBackgroundFillGradientEnabled();
	public:
		std::shared_ptr<ctlImage> getBackImage();
		std::shared_ptr<ctlImage> getForeImage();
		unsigned getBackImageIndex();
		unsigned getForeImageIndex();
		bool setBackImage(unsigned index);
		bool setForeImage(unsigned index);
		imageRepeat getBackImageRepeat();
		imageRepeat getForeImageRepeat();
		void setBackImageRepeat(imageRepeat);
		void setForeImageRepeat(imageRepeat);
	public:
		unsigned char getBackImageAlpha();
		unsigned char getForeImageAlpha();
		void setBackImageAlpha(unsigned char);
		void setForeImageAlpha(unsigned char);
	public:
		void setBackImageMaskColor(ctlColor);
		void setForeImageMaskColor(ctlColor);
		ctlColor getBackImageMaskColor();
		ctlColor getForeImageMaskColor();
		void setBackImageMaskEnable(bool);
		void setForeImageMaskEnable(bool);
		bool getBackImageMaskEnable();
		bool getForeImageMaskEnable();
	public:
		/* 设置控件允许子控件绘制的范围，默认为 false
		 * true 为 getRect()
		 * false 为 getRect().deflate(1, 1) */
		bool isBackgroundCombineRgnEnabled();
		void setBackgroundCombineRgnEnable(bool);
	protected:
		void _background_redraw(_ctlInterior::drawInfo*, bool gdip = false);
		virtual bool _combine_child_rgn(HRGN);
	private:
		void _background_border_directory_fill(_ctlInterior::drawInfo*);
	private:
		bool _background_enable;
		bool _background_fill_gradient_enable;
		ctlColor _background_fill_gradient_end;
		ctlColor _background_fill;
		ctlColor _background_border;
		ctlColor _background_hatch;
		borderStyle _background_border_style;
		fillStyle _background_fill_style;
		unsigned char _background_border_directory;
	private:
		imageRepeat _background_image_back_repeat;
		imageRepeat _background_image_fore_repeat;
		unsigned _background_image_back_index;
		unsigned _background_image_fore_index;
		unsigned char _background_image_back_alpha;
		unsigned char _background_image_fore_alpha;
		bool _background_image_back_mask_enable;
		bool _background_image_fore_mask_enable;
		ctlColor _background_image_back_mask_color;
		ctlColor _background_image_fore_mask_color;
		bool _background_combine_rgn;
	};
	
	inline void IBackground::setBkFillGradientEnd(ctlColor cr, bool enable) {
		_background_fill_gradient_enable = enable;
		if(enable) _background_fill_gradient_end = cr;
		redraw();
	}
	inline ctlColor IBackground::getBkFillGradientEnd() {
		return _background_fill_gradient_end;
	}
	inline bool IBackground::isBackgroundFillGradientEnabled() {
		return _background_fill_gradient_enable;
	}
	inline void IBackground::setBkBorderDirectory(unsigned char uc) {
		_background_border_directory = uc;
		redraw();
	}
	inline unsigned char IBackground::getBkBorderDirectory() {
		return _background_border_directory;
	}
	inline void IBackground::setBkHatchColor(ctlColor color) {
		_background_hatch = color;
		redraw();
	}
	inline ctlColor IBackground::getBkHatchColor() {
		return _background_hatch;
	}
	inline bool IBackground::isBackgroundEnabled() {
		return _background_enable;
	}
	inline void IBackground::enableBackground(bool enable) {
		_background_enable = enable;
		redraw();
	}
	inline void IBackground::setBkFillColor(ctlColor color) {
		_background_fill = color;
		redraw();
	}
	inline void IBackground::setBkBorderColor(ctlColor color) {
		_background_border = color;
		redraw();
	}
	inline ctlColor IBackground::getBkFillColor() {
		return _background_fill;
	}
	inline ctlColor IBackground::getBkBorderColor() {
		return _background_border;
	}
	inline void IBackground::setBkBorderStyle(borderStyle style) {
		_background_border_style = style;
		redraw();
	}
	inline IBackground::borderStyle IBackground::getBkBorderStyle() {
		return _background_border_style;
	}
	inline void IBackground::setBkFillStyle(fillStyle style) {
		_background_fill_style = style;
		redraw();
	}
	inline IBackground::fillStyle IBackground::getBkFillStyle() {
		return _background_fill_style;
	}
	inline IBackground::IBackground() {
		_background_enable = false;
		_background_combine_rgn = true;
		_background_fill_gradient_enable = false;
		_background_border_directory = 0x0f;
		_background_border = 0xff000000;
		_background_hatch = 0xffffffff;
		_background_fill = 0xffffffff;
		_background_border_style = borderStyle::solid;
		_background_fill_style = fillStyle::solid;
		_background_image_back_index = imageNull;
		_background_image_fore_index = imageNull;
		_background_image_back_repeat = imageRepeat::noRepeatXY;
		_background_image_fore_repeat = imageRepeat::noRepeatXY;
		_background_image_back_alpha = 255;
		_background_image_fore_alpha = 255;
		_background_image_back_mask_enable = false;
		_background_image_fore_mask_enable = false;
		_background_image_back_mask_color = 0xff000000;
		_background_image_fore_mask_color = 0xff000000;
	}
	inline bool IBackground::isBackgroundCombineRgnEnabled() {
		return _background_combine_rgn;
	}
	inline void IBackground::setBackgroundCombineRgnEnable(bool enable) {
		_background_combine_rgn = enable;
		redraw();
	}
	inline std::shared_ptr<ctlImage> IBackground::getBackImage() {
		if(getBackImageIndex() != imageNull)
			return getImageQueue()->getElement(_background_image_back_index);
		return std::shared_ptr<ctlImage>(nullptr);
	}
	inline std::shared_ptr<ctlImage> IBackground::getForeImage() {
		if(getForeImageIndex() != imageNull)
			return getImageQueue()->getElement(_background_image_fore_index);
		return std::shared_ptr<ctlImage>(nullptr);
	}
	inline unsigned IBackground::getBackImageIndex() {
		return _background_image_back_index;
	}
	inline unsigned IBackground::getForeImageIndex() {
		return _background_image_fore_index;
	}
	inline bool IBackground::setBackImage(unsigned index) {
		if(getImageQueue()->getQueueSize() <= index)
			return false;
		_background_image_back_index = index;
		redraw();
		return true;
	}
	inline bool IBackground::setForeImage(unsigned index) {
		if(getImageQueue()->getQueueSize() <= index)
			return false;
		_background_image_fore_index = index;
		redraw();
		return true;
	}
	inline IBackground::imageRepeat IBackground::getBackImageRepeat() {
		return _background_image_back_repeat;
	}
	inline IBackground::imageRepeat IBackground::getForeImageRepeat() {
		return _background_image_fore_repeat;
	}
	inline void IBackground::setBackImageRepeat(imageRepeat repeat) {
		_background_image_back_repeat = repeat;
		redraw();
	}
	inline void IBackground::setForeImageRepeat(imageRepeat repeat) {
		_background_image_fore_repeat = repeat;
		redraw();
	}
	inline unsigned char IBackground::getBackImageAlpha() {
		return _background_image_back_alpha;
	}
	inline unsigned char IBackground::getForeImageAlpha() {
		return _background_image_fore_alpha;
	}
	inline void IBackground::setBackImageAlpha(unsigned char alpha) {
		_background_image_back_alpha = alpha;
		redraw();
	}
	inline void IBackground::setForeImageAlpha(unsigned char alpha) {
		_background_image_fore_alpha = alpha;
		redraw();
	}
	inline void IBackground::setBackImageMaskColor(ctlColor color) {
		_background_image_back_mask_color = color;
		redraw();
	}
	inline void IBackground::setForeImageMaskColor(ctlColor color) {
		_background_image_fore_mask_color = color;
		redraw();
	}
	inline ctlColor IBackground::getBackImageMaskColor() {
		return _background_image_back_mask_color;
	}
	inline ctlColor IBackground::getForeImageMaskColor() {
		return _background_image_fore_mask_color;
	}
	inline void IBackground::setBackImageMaskEnable(bool enable) {
		_background_image_back_mask_enable = enable;
		redraw();
	}
	inline void IBackground::setForeImageMaskEnable(bool enable) {
		_background_image_fore_mask_enable = enable;
		redraw();
	}
	inline bool IBackground::getBackImageMaskEnable() {
		return _background_image_back_mask_enable;
	}
	inline bool IBackground::getForeImageMaskEnable() {
		return _background_image_fore_mask_enable;
	}
}

#endif